package com.gitee.wsl.mathematics.matrix.mat3.ext

import com.gitee.wsl.ext.number.isFuzzyZero
import com.gitee.wsl.mathematics.matrix.mat3.MutableMat3f
import com.gitee.wsl.mathematics.vector.ext.cross
import com.gitee.wsl.mathematics.vector.ext.dot
import com.gitee.wsl.mathematics.vector.vec3.MutableVec3f
import com.gitee.wsl.mathematics.vector.vec3.Vec3f


/**
 * Inplace operation: Applies a look-at transform to this matrix.
 */
fun MutableMat3f.lookAt(eyePosition: Vec3f, lookAt: Vec3f, up: Vec3f){
    val z = MutableVec3f(lookAt - eyePosition)
    val fLen = z.length
    if (fLen.isFuzzyZero()) {
        // eye position and look at are equal
        z.z = 1f
    } else {
        z *= 1f / fLen
    }

    var x = z.cross(up)
    val sLen = x.length
    if (sLen.isFuzzyZero()) {
        // forward vector is parallel to up
        if (abs(z.dot(Vec3f.Y_AXIS)) > 0.99f) {
            x = z.cross(Vec3f.NEG_Z_AXIS)
            x = x.normalized
        } else {
            x=z.cross(Vec3f.Y_AXIS)
            x = x.normalized
        }
    } else {
        x *= 1f / sLen
    }

    val y = x.cross(z)

     mul(
        x.x, x.y, x.z,
        y.x, y.y, y.z,
       -z.x, -z.y, -z.z,
    )
}